/*
 * @Author jiangzhiwei
 * @Date 2023-07-20 15:47:06
 * @LastEditors jiangzhiwei
 * @LastEditTime 2023-07-28 11:27:59
 * @FilePath \test-cron\src\components\yc-cron\components\base\common-checkbox-group\index.js
 * @Description 
 */
import { defineComponent } from 'vue-demi'
import { h } from '../../../utils/domutil'
import { emitValue, getSlot, getComponentProp } from '../../../utils/componentutil'
import { VALUE_NAME } from '../../../utils/constant'
import './checkboxgroup.css'

const NAME = 'yc-cron-checkbox-group'

export default defineComponent({
  name: NAME,
  props: {
    [VALUE_NAME]: {
      type: Array,
      default: undefined
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      /** 长按多选信息 */
      multiCheckInfo: {
        /** 是否激活 */
        isActive: false,
        /** 开始的标签 */
        startLabel: undefined,
        /** 结束的标签 */
        finishLabel: undefined,
        /** 勾选/取消勾选 */
        checked: undefined
      }
    }
  },
  mounted () {
    document.addEventListener('mouseup', this.mouseup)
  },
  unmounted () {
    document.removeEventListener('mouseup', this.mouseup)
  },
  methods: {
    updateValue (label, isChecked) {
      const list = [...this[VALUE_NAME]]
      if (isChecked) { // 选中
        if (!list.includes(label)) { // 如果不存在
          list.push(label)
          emitValue(this, list)
        }
      } else { // 取消选中
        const index = list.indexOf(label)
        if (index > -1) { // 如果存在
          list.splice(index, 1)
          emitValue(this, list)
        }
      }
    },
    /**
     * @Author jiangzhiwei
     * @Date 2023-07-21 10:07:49
     * @Description 开始多选。子组件调用
     * @param {string | number | boolean} label 多选按钮对应值
     * @param {boolean} checked 勾选/取消勾选
     * @return {undefined}
     */
    startMultiCheck (label, checked) {
      const info = this.multiCheckInfo
      info.startLabel = label
      info.finishLabel = label
      info.checked = checked
      info.isActive = true
    },
    /**
     * @Author jiangzhiwei
     * @Date 2023-07-21 11:02:27
     * @Description 鼠标移动中。子组件调用
     * @param {string | number | boolean} label 多选按钮对应值
     * @return {undefined}
     */
    onPointermove (label) {
      if (this.multiCheckInfo.isActive) { // 如果是在多选中
        this.continueMultiCheck(label)
      }
    },
    /**
     * @Author jiangzhiwei
     * @Date 2023-07-21 10:08:53
     * @Description 持续多选
     * @param {string | number | boolean} label 当前所在多选按钮对应值
     * @return {undefined}
     */
    continueMultiCheck (label) {
      const info = this.multiCheckInfo
      if (info.finishLabel !== label) { // 如果结束的值发生了改变，表示移动到别的多选按钮上了
        const oldValues = this.getChildrenValues(info.startLabel, info.finishLabel)
        this.setMultiChecked(oldValues, !info.checked)
        info.finishLabel = label
        const newValues = this.getChildrenValues(info.startLabel, info.finishLabel)
        this.setMultiChecked(newValues, info.checked)
      }
    },
    /**
     * @Author jiangzhiwei
     * @Date 2023-07-21 10:34:44
     * @Description 设置批量选择
     * @param {Array} labels 值数组
     * @param {boolean} checked 勾选/取消勾选
     * @return {undefined}
     */
    setMultiChecked (labels, checked) {
      const list = this[VALUE_NAME]
      if (checked) { // 勾选
        labels.forEach(label => {
          if (!list.includes(label)) { // 不包含该值
            list.push(label)
          }
        })
      } else { // 取消勾选
        labels.forEach(label => {
          const index = list.indexOf(label)
          if (index > -1) { // 包含该值
            list.splice(index, 1)
          }
        })
      }
      emitValue(this, list)
    },
    /**
     * @Author jiangzhiwei
     * @Date 2023-07-21 10:48:16
     * @Description 根据两个子组件的值，获取这两个组件及其他们之间的组件的值构成的数组
     * @param {number} label1 第一个组件的值
     * @param {number} label2 第二个组件的值
     * @return {Array}
     */
    getChildrenValues (label1, label2) {
      // 因为方法是默认插槽内组件调用，所以一定有子组件
      const children = getSlot(this)
      let startIndex = children.findIndex(item => getComponentProp(item, 'label') === label1)
      let finishIndex = children.findIndex(item => getComponentProp(item, 'label') === label2)
      if (startIndex > finishIndex) { // 如果顺序反了，则进行交换
        const tempIndex = startIndex
        startIndex = finishIndex
        finishIndex = tempIndex
      }
      return children.slice(startIndex, finishIndex + 1).map(item => getComponentProp(item, 'label'))
    },
    /** 松开鼠标停止多选 */
    mouseup () {
      this.multiCheckInfo.isActive = false
    }
  },
  render () {
    return h(
      'article',
      {
        class: { [NAME]: true }
      },
      getSlot(this)
    )
  }
})